package ga.cross;

import ga.GARun;
import ga.individuals.Individual;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class Segment implements CrossMethod {

	@Override
	public Collection<Individual> method(Collection<Individual> individuals) {
		if (individuals.size() != 2) {
			return null;
		}
		Double random = Math.random();
		List<Individual> listIndividuals = new LinkedList<Individual>(individuals);
		Long firstIndividual = Double.doubleToRawLongBits(listIndividuals.get(0).getIndividualValue());
		Long sndIndividual = Double.doubleToRawLongBits(listIndividuals.get(1).getIndividualValue());
		Long newFirstIndividual = 0x0000000000000000L;
		Long newSndIndividual = 0x0000000000000000L;
		Random r = new Random(System.currentTimeMillis());
		for (int i = 0; i < GARun.bitsInDouble; i++) {
			if (r.nextDouble() >= random) {
				newFirstIndividual = setBit(newFirstIndividual, firstIndividual, i);
				newSndIndividual = setBit(newSndIndividual, sndIndividual, i);
			} else {
				newFirstIndividual = setBit(newFirstIndividual, sndIndividual, i);
				newSndIndividual = setBit(newSndIndividual, firstIndividual, i);
			}
		}
		Collection<Individual> newIndividuals = new LinkedList<Individual>();
		newIndividuals.add(new Individual(Double.longBitsToDouble(newFirstIndividual)));
		newIndividuals.add(new Individual(Double.longBitsToDouble(newSndIndividual)));
		return newIndividuals;
	}
	
	private long setBit (long individualToSet, long individualToGet, int bitToSet) {
		Long mask = 0x0000000000000001L << bitToSet;
		Long bit = individualToGet & mask;
		if (bit == 0) {
			return individualToSet & (~mask);
		} else {
			return individualToSet | mask;
		}
	}

}
